import * as Cesium from 'cesium'
import type { ModelPosition } from '../types/model'

interface LoadedModelInfo {
  entity: Cesium.Entity
  originalUrl: string
  filename: string
  position: ModelPosition
}

export class ModelLoader {
  private loadedModels = new Map<string, LoadedModelInfo>()

  constructor(private viewer: Cesium.Viewer) {}

  async loadFromFile(file: File, position?: ModelPosition): Promise<Cesium.Entity> {
    try {
      // 创建文件URL
      const url = URL.createObjectURL(file)
      
      // 设置默认位置（北京）
      const defaultPosition: ModelPosition = {
        longitude: 116.397,
        latitude: 39.909,
        height: 1000
      }
      
      const finalPosition = position || defaultPosition
      
      // 创建模型实体
      const entity = this.viewer.entities.add({
        name: file.name,
        position: Cesium.Cartesian3.fromDegrees(
          finalPosition.longitude,
          finalPosition.latitude,
          finalPosition.height
        ),
        model: {
          uri: url,
          minimumPixelSize: 128,
          maximumScale: 20000,
          scale: 1.0,
          shadows: Cesium.ShadowMode.ENABLED,
          heightReference: Cesium.HeightReference.NONE,
          color: new Cesium.ConstantProperty(Cesium.Color.WHITE),
          colorBlendMode: new Cesium.ConstantProperty(Cesium.ColorBlendMode.HIGHLIGHT),
          colorBlendAmount: new Cesium.ConstantProperty(0.0)
        }
      })

      // 存储模型信息
      this.loadedModels.set(entity.id, {
        entity: entity,
        originalUrl: url,
        filename: file.name,
        position: finalPosition
      })

      console.log('模型加载成功:', file.name)
      return entity

    } catch (error) {
      console.error('模型加载失败:', error)
      throw new Error(`模型加载失败: ${(error as Error).message}`)
    }
  }

  async loadFromUrl(url: string, position?: ModelPosition, name = 'Model'): Promise<Cesium.Entity> {
    try {
      const defaultPosition: ModelPosition = {
        longitude: 116.397,
        latitude: 39.909,
        height: 0
      }
      
      const finalPosition = position || defaultPosition
      
      const entity = this.viewer.entities.add({
        name: name,
        position: Cesium.Cartesian3.fromDegrees(
          finalPosition.longitude,
          finalPosition.latitude,
          finalPosition.height
        ),
        model: {
          uri: url,
          minimumPixelSize: 128,
          maximumScale: 20000,
          scale: 1.0,
          shadows: Cesium.ShadowMode.ENABLED,
          heightReference: Cesium.HeightReference.NONE
        }
      })

      this.loadedModels.set(entity.id, {
        entity: entity,
        originalUrl: url,
        filename: name,
        position: finalPosition
      })

      return entity

    } catch (error) {
      console.error('从URL加载模型失败:', error)
      throw new Error(`从URL加载模型失败: ${(error as Error).message}`)
    }
  }

  updatePosition(entity: Cesium.Entity, longitude: number, latitude: number, height: number): void {
    if (entity && entity.position) {
      entity.position = new Cesium.ConstantPositionProperty(
        Cesium.Cartesian3.fromDegrees(longitude, latitude, height)
      )
      
      // 更新存储的位置信息
      const modelInfo = this.loadedModels.get(entity.id)
      if (modelInfo) {
        modelInfo.position = { longitude, latitude, height }
      }
    }
  }

  updateOrientation(entity: Cesium.Entity, heading: number, pitch: number, roll: number): void {
    if (entity && entity.model && entity.position) {
      const position = entity.position.getValue(Cesium.JulianDate.now())
      if (position) {
        entity.orientation = new Cesium.ConstantProperty(
          Cesium.Transforms.headingPitchRollQuaternion(
            position,
            new Cesium.HeadingPitchRoll(
              Cesium.Math.toRadians(heading),
              Cesium.Math.toRadians(pitch),
              Cesium.Math.toRadians(roll)
            )
          )
        )
      }
    }
  }

  updateScale(entity: Cesium.Entity, scale: number): void {
    if (entity && entity.model) {
      entity.model.scale = new Cesium.ConstantProperty(scale)
    }
  }

  removeModel(entity: Cesium.Entity): void {
    if (entity) {
      // 清理URL对象
      const modelInfo = this.loadedModels.get(entity.id)
      if (modelInfo && modelInfo.originalUrl && modelInfo.originalUrl.startsWith('blob:')) {
        URL.revokeObjectURL(modelInfo.originalUrl)
      }
      
      // 从场景中移除
      this.viewer.entities.remove(entity)
      
      // 从存储中移除
      this.loadedModels.delete(entity.id)
    }
  }

  removeAllModels(): void {
    this.loadedModels.forEach((modelInfo) => {
      if (modelInfo.originalUrl && modelInfo.originalUrl.startsWith('blob:')) {
        URL.revokeObjectURL(modelInfo.originalUrl)
      }
      this.viewer.entities.remove(modelInfo.entity)
    })
    this.loadedModels.clear()
  }

  getModelInfo(entity: Cesium.Entity): LoadedModelInfo | undefined {
    return this.loadedModels.get(entity.id)
  }

  getAllModels(): LoadedModelInfo[] {
    return Array.from(this.loadedModels.values())
  }

  // 设置模型的显示/隐藏
  setModelVisible(entity: Cesium.Entity, visible: boolean): void {
    if (entity && entity.model) {
      entity.show = visible
    }
  }

  // 设置模型透明度
  setModelOpacity(entity: Cesium.Entity, opacity: number): void {
    if (entity && entity.model) {
      entity.model.color = new Cesium.ConstantProperty(Cesium.Color.WHITE.withAlpha(opacity))
    }
  }

  // 获取模型的边界框
  getModelBounds(entity: Cesium.Entity): Cesium.BoundingSphere | null {
    if (entity && this.viewer.entities.contains(entity) && entity.position) {
      try {
        const position = entity.position.getValue(Cesium.JulianDate.now())
        if (position) {
          return Cesium.BoundingSphere.fromPoints([position])
        }
      } catch (error) {
        console.warn('获取模型边界框失败:', error)
      }
    }
    return null
  }

  // 创建测试立方体 (10km×10km×100m)
  createTestCube(position?: ModelPosition): Cesium.Entity {
    const defaultPosition: ModelPosition = {
      longitude: 116.397,
      latitude: 39.909,
      height: 50
    }
    
    const finalPosition = position || defaultPosition
    
    const entity = this.viewer.entities.add({
      name: '测试立方体 (10km×10km×100m)',
      position: new Cesium.ConstantPositionProperty(
        Cesium.Cartesian3.fromDegrees(
          finalPosition.longitude,
          finalPosition.latitude,
          finalPosition.height
        )
      ),
      box: {
        dimensions: new Cesium.Cartesian3(10000, 10000, 100),
        material: new Cesium.ColorMaterialProperty(Cesium.Color.CYAN.withAlpha(0.7)),
        outline: true,
        outlineColor: new Cesium.ConstantProperty(Cesium.Color.BLUE),
        heightReference: Cesium.HeightReference.NONE
      }
    })

    // 存储模型信息
    this.loadedModels.set(entity.id, {
      entity: entity,
      originalUrl: 'test-cube',
      filename: '测试立方体',
      position: finalPosition
    })

    return entity
  }
}
